﻿using SuperSocket.ClientEngine;
using SuperSocket.ProtoBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;

namespace ETS_FinancialData_sync_toolsForClient
{
    public class TcpClient
    {
        private bool _Error = false;
        private EasyClient _TcpClient;
        private System.Timers.Timer _HeartBeat;
        //public delegate void Received(byte[] buffer);
        //public event Received DataReceived;
        public delegate void DeClosed(object sender, EventArgs e);
        public event DeClosed Closed;
        public bool IsConnected
        {
            get { return _TcpClient.IsConnected; }
        }

        public TcpClient(IPAddress ip, int port)
        {
            _TcpClient = new EasyClient();
            //_TcpClient.DataReceived += TcpDataReceived;
            _TcpClient.Connected += _TcpClient_Connected;
            _TcpClient.Error += _TcpClient_Error;
            _HeartBeat = new System.Timers.Timer(1000);
            _HeartBeat.Elapsed += TimerElapsed;
            _HeartBeat.AutoReset = true;
            
        }

        private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)//心跳
        {
            byte[] sendData = Encoding.UTF8.GetBytes(string.Format("Heart#{0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
            this.Send();
        }

        private void _TcpClient_Error(object sender, ErrorEventArgs e)
        {
            _HeartBeat.Stop();
            if (!_Error)
            {
                if (!this.TryConnect())
                    Closed(_TcpClient, e);
            }
        }

        private void _TcpClient_Connected(object sender, EventArgs e)
        {
            _HeartBeat.Start();
        }

        //private void TcpDataReceived(object sender, DataEventArgs e)
        //{
        //    if (DataReceived != null)
        //    {
        //        byte[] buffer = new byte[e.Length];
        //        Array.Copy(e.Data, buffer, e.Length);
        //        this.DataReceived(buffer);
        //    }
        //}
        IPEndPoint port1;
        public void Connect()
        {
            try
            {
                port1 = new System.Net.IPEndPoint(IPAddress.Parse("127.0.0.1"), 10100);
                if (!_TcpClient.IsConnected)
                    _TcpClient.ConnectAsync(port1).Wait(); ;
            }
            catch (Exception ex)
            {

            }
        }

        public void Close()
        {
            _TcpClient.Close();
            _HeartBeat.Stop();
            this.Closed(_TcpClient, null);
        }

        private bool TryConnect()
        {
            _Error = true;
            _HeartBeat.Stop();

            for (int i = 0; i < 3; i++)
            {
                _TcpClient.Close();
                _TcpClient.ConnectAsync(port1);
                Thread.Sleep(1000);
                if (this.IsConnected)
                {
                    _HeartBeat.Start();
                    _Error = false;
                    return true;
                }
            }
            _Error = false;
            return false;
        }

        public void Send()
        {
            //_TcpClient.Send(new ArraySegment<byte>(sendData));
            byte[] sendData = Encoding.UTF8.GetBytes(string.Format("Heart#{0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
            _TcpClient.Send(new ArraySegment<byte>(sendData));
        }

        public void Send(string com, string sendstr)
        {
            byte[] sendData = Encoding.Default.GetBytes(string.Format("{0}#{1}\r\n", com, sendstr));
            _TcpClient.Send(new ArraySegment<byte>(sendData));
        }

    }

    public class MyFixedHeaderReceiveFilter : FixedHeaderReceiveFilter<StringPackageInfo>
    {
        public MyFixedHeaderReceiveFilter() : base(4) { }

        public override StringPackageInfo ResolvePackage(IBufferStream bufferStream)
        {
            var data = System.Text.Encoding.UTF8.GetString(bufferStream.Buffers);

            Console.WriteLine(data);
            return new StringPackageInfo("AAA", data, null);
        }

        protected override int GetBodyLengthFromHeader(IBufferStream bufferStream, int length)
        {
            var header = bufferStream.Buffers[0];
            int bodyLength = (int)(header.Array[header.Offset] | header.Array[header.Offset + 1] << 8 | header.Array[header.Offset + 2] << 16 | header.Array[header.Offset + 3] << 24);
            return bodyLength;
            //throw new NotImplementedException();
        }
    }
    public class MyTerminatorReceiveFilter : TerminatorReceiveFilter<StringPackageInfo>
    {
        //private readonly Encoding m_Encoding;
        //private readonly IStringParser m_StringParser;

        /// <summary>
        /// Initializes a new instance of the <see cref="TerminatorReceiveFilter" /> class.
        /// </summary>
        /// <param name="terminator">The terminator.</param>
        /// <param name="encoding">The encoding.</param>
        /// <param name="stringParser">The string parser.</param>
        //public My02ReceiveFilter(byte[] terminator, Encoding encoding, IStringParser stringParser)
        //    : base(terminator)
        //{
        //    m_Encoding = encoding;
        //    m_StringParser = stringParser;
        //}
        public MyTerminatorReceiveFilter()
            : base(Encoding.ASCII.GetBytes("||"))
        {

        }
        /// <summary>
        /// Resolves the package.
        /// </summary>
        /// <param name="bufferStream">The received buffer stream.</param>
        /// <returns></returns>
        public override StringPackageInfo ResolvePackage(IBufferStream bufferStream)
        {
            //var encoding = m_Encoding;
            var totalLen = (int)bufferStream.Length - SearchState.Mark.Length;
            //return new StringPackageInfo(bufferStream.ReadString(totalLen, encoding), m_StringParser);
            TestRequestParser stringparser = new TestRequestParser();
            return new StringPackageInfo(bufferStream.ReadString(totalLen, Encoding.UTF8), stringparser);
        }
        public class TestRequestParser : IStringParser
        {
            public void Parse(string source, out string key, out string body, out string[] parameters)
            {
                key = string.Empty;
                body = string.Empty;
                parameters = null;
                body=source;
                int pos = source.IndexOf('#');

                if (pos <= 0)
                    return;

                key = source.Substring(0, pos);
                body = source.Substring(pos + 2);

                if (!string.IsNullOrEmpty(body))
                    parameters = body.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            }
        }
    }

}